﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinanSoft.Entities;
using FinanSoft.DataLayer;
using FinanSoft.Utilities;

namespace FinanSoft.BusinessLayer.BuySaleStrategy
{
    public class CreditNoteDocManager : BuySaleDocManager
    {
        #region Atributos
        private bool _IsError;
        private String _ErrorMessage;
        #endregion

        #region Constructor
        public CreditNoteDocManager()
        {
            _IsError = false;
            _ErrorMessage = "";
        }
        #endregion

        #region Métodos
        /// <summary>
        /// Método que se encarga de guardar un documento de nota de crédito
        /// </summary>
        /// <param name="document">Documento que se desea guardar</param>
        /// <param name="docType">Tipo de documento NCA o NCS</param>
        /// <returns>Retorna si hubo o no éxito en la operación</returns>
        public bool SaveDocument(Entities.Document document, string docType)
        {
            // Se obtiene el tipo de documento
            DocType type = DocumentTypeManager.GetInstance().GetType(docType);
            // Se intenta guardar en bd el encabezado del documento primero para que nos devuelva el id
            int docId = BuySaleDataManager.GetInstance().SaveDocumentHeader(document, type);
            if (docId == Constants.INVALID_ID)
            {
                _IsError = true;
                _ErrorMessage = Constants.ERROR_SAVING_DOC;
                return false;
            }
            // Intentamos guardar los artículos para el documento que se insertó anteriormente
            foreach (DocDetail detail in document.detalleDoc)
            {
                string docCode = DocumentTypeManager.GetInstance().GetType(docType).CurrentNumber.ToString();
                AuxiliarAccount auxAccount = AuxiliaryAccountManager.GetInstance().GetAuxiliarAccount(document.IdCuentaAuxiliar);
                ItemStoreRoomInfo itemStoreInfo = detail.Item.GetStoreRoomInfo(detail.StoreRoom.Id);
                Currency docCurrency = MoneyManager.GetInstance().GetCurrency(document.IdMoneda);
                List<AccountingEntryDetail> invoiceDetails = new List<AccountingEntryDetail>();
                // Estamos usando el valor de la bodega en la que se ingresa el artículo
                bool result = ItemManager.GetInstance().MakeInventoryInputMovement(detail.Item.Id, detail.StoreRoom.Id, itemStoreInfo.CostoUnitario, (int)Math.Round(detail.Quantity), itemStoreInfo.CuentaCostoVentas.AccountID, Constants.INVALID_ID, docType);
                if (!result)
                {
                    _ErrorMessage = ItemManager.GetInstance().ErrorMessage;
                    return false;
                }
                Account refundAccount = CatalogManager.GetInstance().GetAccountingCatalog().GetSpecialAccounts(Constants.SpecialType.salesRefund)[0];
                double refundLocalAmount = Math.Round(detail.Quantity * detail.UnitCost * docCurrency.ToLocalCurrency, 2);
                double refundSystemAmount = Math.Round(refundLocalAmount / MoneyManager.GetInstance().SystemCurrency.ToLocalCurrency, 2);
                invoiceDetails.Add(AccountingEntryManager.GetInstance().BuildAccountingEntryDetail(
                    refundAccount.AccountID, refundSystemAmount, refundLocalAmount, Constants.AccountingEntryType.debit, Constants.INVALID_ID));
                invoiceDetails.Add(AccountingEntryManager.GetInstance().BuildAccountingEntryDetail(
                    auxAccount.Parent, refundSystemAmount, refundLocalAmount, Constants.AccountingEntryType.credit, auxAccount.AccountID));

                // Hacemos el asiento para el impuesto de ventas
                double taxLocalAmount = Math.Round(detail.Quantity * detail.UnitCost * detail.Tax.Porcentaje * docCurrency.ToLocalCurrency, 2);
                double taxSystemAmount = Math.Round(taxLocalAmount / MoneyManager.GetInstance().SystemCurrency.ToLocalCurrency, 2);
                int taxId = CatalogManager.GetInstance().GetAccountingCatalog().GetSpecialAccounts(Constants.SpecialType.salesTaxToPay)[0].AccountID;
                invoiceDetails.Add(AccountingEntryManager.GetInstance().BuildAccountingEntryDetail
                    (auxAccount.Parent, taxSystemAmount, taxLocalAmount, Constants.AccountingEntryType.credit, auxAccount.AccountID));
                invoiceDetails.Add(AccountingEntryManager.GetInstance().BuildAccountingEntryDetail
                    (taxId, taxSystemAmount, taxLocalAmount, Constants.AccountingEntryType.debit, Constants.INVALID_ID));
                bool entryResult = AccountingEntryManager.GetInstance().CreateAndRecordAccountingEntry(
                    docType, document.fechaVencimiento, document.fechaEmision, PeriodManager.GetInstance().GetCurrentAccountingPeriod().GetCurrentSeason().Id,
                    "Código " + docCode, "", "", invoiceDetails);
                if (!entryResult)
                {
                    _IsError = true;
                    _ErrorMessage = AccountingEntryManager.GetInstance().ErrorMessage;
                    return false;
                }
                bool noErrorDB = BuySaleDataManager.GetInstance().SaveDocumentArticle(detail, docId);
                if (!noErrorDB)
                {
                    _IsError = true;
                    _ErrorMessage = Constants.ERROR_SAVING_DOCS_ARTICLES;
                    return false;
                }
            }
            DocumentTypeManager.GetInstance().IncreaseDocumentConsecutiveNumber(docType);
            return true;
        }

        public string GetErrorMessage()
        {
            return _ErrorMessage;
        }
        #endregion
    }
}
